home *** CD-ROM | disk | FTP | other *** search
- /*
- File: Common.c
-
- Contains: HackTV cross-platform common code
-
- Written by: Gary Woodcock
- Updated by: Brian Friedkin
-
- Copyright: © 1992-1998 by Apple Computer, Inc.
- */
- #include <QTML.h>
- #include <Endian.h>
- #include <Menus.h>
- #include <Printing.h>
- #include <Script.h>
- #include <Scrap.h>
- #include <QuickTimeComponents.h>
- #include "Globals.h"
- #include "Common.h"
-
- // Disable warnings associated with "\p" strings
- #if TARGET_OS_WIN32
- #pragma warning(disable: 4129)
- #endif
-
- static OSErr XorRectToRgn(Rect *srcRectA, Rect *srcRectB, RgnHandle *destRgn);
-
- /* ---------------------------------------------------------------------- */
-
- void InitializeSequenceGrabber(void)
- {
- ComponentDescription theDesc;
- ComponentResult result = noErr;
- GrafPtr savedPort;
- Component sgCompID;
-
- gQuitFlag = false;
- gSeqGrabber = 0L;
- gVideoChannel = 0L;
- gSoundChannel = 0L;
- gMonitorPICT = nil;
- gPrintRec = (THPrint) NewHandleClear (sizeof (TPrint));
-
- // Find and open a sequence grabber
- theDesc.componentType = SeqGrabComponentType;
- theDesc.componentSubType = 0L;
- theDesc.componentManufacturer = 'appl';
- theDesc.componentFlags = 0L;
- theDesc.componentFlagsMask = 0L;
- sgCompID = FindNextComponent (nil, &theDesc);
- if (sgCompID != 0L)
- gSeqGrabber = OpenComponent (sgCompID);
-
- // If we got a sequence grabber, set it up
- if (gSeqGrabber != 0L)
- {
- // Get the monitor
- CreateMonitorWindow();
- if (gMonitor != nil)
- {
- // Display the monitor window
- GetPort (&savedPort);
- MacSetPort (gMonitor);
- MacMoveWindow(gMonitor, 10, 30 + GetMBarHeight(), 0);
- MacShowWindow (gMonitor);
-
- // Initialize the sequence grabber
- result = SGInitialize (gSeqGrabber);
- if (result == noErr)
- {
- result = SGSetGWorld (gSeqGrabber, (CGrafPtr) gMonitor, nil);
-
- // Get a video channel
- result = SGNewChannel (gSeqGrabber, VideoMediaType, &gVideoChannel);
- if ((gVideoChannel != nil) && (result == noErr))
- {
- short width;
- short height;
-
- gQuarterSize = false;
- gHalfSize = true;
- gFullSize = false;
-
- result = SGGetSrcVideoBounds (gVideoChannel, &gActiveVideoRect);
- width = (gActiveVideoRect.right - gActiveVideoRect.left) / 2;
- height = (gActiveVideoRect.bottom - gActiveVideoRect.top) / 2;
- SizeWindow (gMonitor, width, height, false);
-
- result = SGSetChannelUsage (gVideoChannel, seqGrabPreview | seqGrabRecord | seqGrabPlayDuringRecord);
- result = SGSetChannelBounds (gVideoChannel, &(gMonitor->portRect));
- }
-
- // Get a sound channel
- result = SGNewChannel (gSeqGrabber, SoundMediaType, &gSoundChannel);
-
- if ((gSoundChannel != nil) && (result == noErr))
- {
- if (gSoundChannel != nil)
- {
- result = SGSetChannelUsage (gSoundChannel, seqGrabPreview | seqGrabRecord);
-
- // Set the volume low to prevent feedback when we start the preview,
- // in case the mic is anywhere near the speaker.
- result = SGSetChannelVolume (gSoundChannel, 0x0010);
- }
- }
-
- // Get the alignment proc (for use when dragging the monitor)
- result = SGGetAlignmentProc (gSeqGrabber, &gSeqGrabberAlignProc);
- }
-
- // Go!
- if (result == noErr)
- result = SGStartPreview (gSeqGrabber);
- MacSetPort (savedPort);
- }
- }
- }
-
- /* ---------------------------------------------------------------------- */
-
- // Specify and setup a file to contain this track's data
- static ComponentResult SetTrackFile(SGChannel theChannel, StringPtr prompt, StringPtr defaultName)
- {
- StandardFileReply reply;
- ComponentResult err;
- SGOutput theOutput;
- AliasHandle alias = 0;
-
- // Get the destination filename
- StandardPutFile(prompt, defaultName, &reply);
- if (!reply.sfGood)
- {
- err = fnfErr;
- goto bail;
- }
-
- // Make an alias from the filename
- if (err = QTNewAlias(&reply.sfFile, &alias, true)) goto bail;
-
- // Create an output from this file
- if (err = SGNewOutput(gSeqGrabber, (Handle)alias, rAliasType, seqGrabToDisk, &theOutput)) goto bail;
-
- // Associate this output with the specified channel
- if (err = SGSetChannelOutput(gSeqGrabber, theChannel, theOutput)) goto bail;
-
- bail:
- if (alias) DisposeHandle((Handle)alias);
- return err;
- }
-
- /* ---------------------------------------------------------------------- */
-
- // Record a movie
- void DoRecord(void)
- {
- long err;
- StandardFileReply reply;
-
- // Stop everything while the dialogs are up
- SGStop(gSeqGrabber);
-
- // Get the destination filename
- StandardPutFile("\pSave new movie file as:", "\pHack.mov", &reply);
- if (!reply.sfGood)
- {
- err = fnfErr;
- goto bail;
- }
- if ((err = SGSetDataOutput(gSeqGrabber, &reply.sfFile, seqGrabToDisk)))
- goto bail;
-
- // Ask use for separate video and sound track files if requested
- if (gSoundChannel && gRecordSound && gVideoChannel && gRecordVideo && gSplitTracks)
- {
- if ((err = SetTrackFile(gVideoChannel, "\pSave video track file as:", "\pHackVideo.trk")))
- goto bail;
- if ((err = SetTrackFile(gSoundChannel, "\pSave sound track file as:", "\pHackSound.trk")))
- goto bail;
- }
-
- // If not recording sound or video, then "disable" those channels
- if (gSoundChannel && !gRecordSound)
- SGSetChannelUsage(gSoundChannel, 0);
- if (gVideoChannel && !gRecordVideo)
- SGSetChannelUsage(gVideoChannel, 0);
-
- // Attempt to recover the preview area obscured by dialogs
- #if TARGET_OS_WIN32
- UpdatePort(gMonitor);
- #endif
- SGUpdate(gSeqGrabber, 0);
-
- // Make the movie file
- DeleteMovieFile(&reply.sfFile);
- if (err = CreateMovieFile(&reply.sfFile, 'TVOD', smSystemScript,
- createMovieFileDontOpenFile | createMovieFileDontCreateMovie | createMovieFileDontCreateResFile,
- nil, nil)) goto bail;
-
- FlushEvents(mDownMask+mUpMask,0);
-
- // Record!
- if (err = SGStartRecord(gSeqGrabber))
- goto bail;
-
- while (!Button() && (err == noErr))
- {
- err = SGIdle(gSeqGrabber);
- }
-
- // If we recorded until we ran out of space, then allow SGStop to be
- // called to write the movie resource. The assumption here is that the
- // data output filled up but the disk has enough free space left to
- // write the movie resource.
- if (!((err == dskFulErr) || (err != eofErr)))
- goto bail;
- err = SGStop(gSeqGrabber);
- NoteAlert(kMovieHasBeenRecordedAlertID, 0);
- err = SGStartPreview(gSeqGrabber);
-
- return;
-
- bail:
- SGPause(gSeqGrabber, false);
- SGStartPreview(gSeqGrabber);
- }
-
- /* ---------------------------------------------------------------------- */
-
- void DoAboutDialog(void)
- {
- short itemHit;
- DialogPtr aboutDialog;
-
- aboutDialog = GetNewDialog(kAboutDLOGID, nil, (WindowPtr)-1L);
-
- // Do the boring about dialog
- SetDialogDefaultItem(aboutDialog, 1);
- MacShowWindow(aboutDialog);
- do
- {
- ModalDialog(nil, &itemHit);
- }
- while (itemHit != 1);
- DisposeDialog(aboutDialog);
- }
-
- /* ---------------------------------------------------------------------- */
-
- void DoPageSetup(void)
- {
- PrOpen();
- PrStlDialog(gPrintRec);
- PrClose();
- }
-
- /* ---------------------------------------------------------------------- */
-
- void DoPrint(void)
- {
- TPPrPort printPort;
- TPrStatus printStatus;
- ComponentResult err;
- Rect tempRect;
-
- // Copy a frame from the monitor
- if (gMonitorPICT != nil)
- KillPicture (gMonitorPICT);
- gMonitorPICT = nil;
- err = SGGrabPict(gSeqGrabber, &gMonitorPICT, nil, 0, grabPictOffScreen);
- if ((err == noErr) && (gMonitorPICT != nil))
- {
- // Print it
- HLock((Handle) gMonitorPICT);
- PrOpen();
- if (PrJobDialog (gPrintRec))
- {
- printPort = PrOpenDoc (gPrintRec, nil, nil);
- err = PrError();
- PrOpenPage (printPort, 0);
- err = PrError();
-
- tempRect = (**gMonitorPICT).picFrame;
- tempRect.left = EndianS16_BtoN(tempRect.left);
- tempRect.top = EndianS16_BtoN(tempRect.top);
- tempRect.right = EndianS16_BtoN(tempRect.right);
- tempRect.bottom = EndianS16_BtoN(tempRect.bottom);
- DrawPicture(gMonitorPICT, &tempRect);
-
- PrClosePage (printPort);
- err = PrError();
- PrCloseDoc (printPort);
- err = PrError();
- if ((**gPrintRec).prJob.bJDocLoop == bSpoolLoop)
- {
- PrPicFile (gPrintRec, 0, 0, 0, &printStatus);
- err = PrError();
- }
- }
- PrClose();
- err = PrError();
- HUnlock((Handle) gMonitorPICT);
- }
- }
-
- /* ---------------------------------------------------------------------- */
-
- void DoCopyToClipboard(void)
- {
- ComponentResult err;
-
- // Copy a frame from the monitor
- if (gMonitorPICT != nil)
- KillPicture (gMonitorPICT);
- gMonitorPICT = nil;
- err = SGGrabPict (gSeqGrabber, &gMonitorPICT, nil, 0, grabPictOffScreen);
- if ((err == noErr) && (gMonitorPICT != nil))
- {
- err = ZeroScrap();
- HLock ((Handle) gMonitorPICT);
- err = PutScrap (GetHandleSize ((Handle) gMonitorPICT), 'PICT', *(Handle)gMonitorPICT);
- HUnlock ((Handle) gMonitorPICT);
- }
- }
-
- /* ---------------------------------------------------------------------- */
-
- static pascal Boolean
- SeqGrabberModalFilterProc (DialogPtr theDialog, EventRecord *theEvent,
- short *itemHit, long refCon)
- {
- // Ordinarily, if we had multiple windows we cared about, we'd handle
- // updating them in here, but since we don't, we'll just clear out
- // any update events meant for us
-
- Boolean handled = false;
-
- if ((theEvent->what == updateEvt) &&
- ((WindowPtr) theEvent->message == (WindowPtr) refCon))
- {
- WindowPtr wPtr = (WindowPtr) refCon;
- BeginUpdate (wPtr);
- EndUpdate (wPtr);
- handled = true;
- }
- return (handled);
- }
-
- /* ---------------------------------------------------------------------- */
-
- void DoVideoSettings(void)
- {
- Rect newActiveVideoRect;
- Rect adjustedActiveVideoRect;
- Rect curBounds, curVideoRect, newVideoRect, newBounds;
- short width, height;
- ComponentResult err;
- GrafPtr savedPort;
- RgnHandle deadRgn;
- SGModalFilterUPP seqGragModalFilterUPP;
-
- // Get our current state
- err = SGGetChannelBounds (gVideoChannel, &curBounds);
- err = SGGetVideoRect (gVideoChannel, &curVideoRect);
-
- // Pause
- err = SGPause (gSeqGrabber, true);
-
- // Do the dialog thang
- seqGragModalFilterUPP = (SGModalFilterUPP)NewSGModalFilterProc(SeqGrabberModalFilterProc);
- err = SGSettingsDialog(gSeqGrabber, gVideoChannel, 0,
- nil, 0L, seqGragModalFilterUPP, (long)StripAddress ((Ptr) gMonitor));
- DisposeRoutineDescriptor(seqGragModalFilterUPP);
-
- // What happened?
- err = SGGetVideoRect (gVideoChannel, &newVideoRect);
- err = SGGetSrcVideoBounds (gVideoChannel, &newActiveVideoRect);
-
- // Set up our port
- GetPort (&savedPort);
- MacSetPort (gMonitor);
-
- // Has our active rect changed?
- // If so, it's because our video standard changed (e.g., NTSC to PAL),
- // and we need to adjust our monitor window
- if (!MacEqualRect (&gActiveVideoRect, &newActiveVideoRect))
- {
- if (gFullSize)
- {
- width = newActiveVideoRect.right - newActiveVideoRect.left;
- height = newActiveVideoRect.bottom - newActiveVideoRect.top;
-
- gActiveVideoRect = newActiveVideoRect;
- SizeWindow (gMonitor, width, height, false);
- err = SGSetChannelBounds (gVideoChannel, &(gMonitor->portRect));
- }
- else if (gHalfSize)
- {
- width = (newActiveVideoRect.right - newActiveVideoRect.left) / 2;
- height = (newActiveVideoRect.bottom - newActiveVideoRect.top) / 2;
-
- gActiveVideoRect = newActiveVideoRect;
- SizeWindow (gMonitor, width, height, false);
- err = SGSetChannelBounds (gVideoChannel, &(gMonitor->portRect));
- }
- else if (gQuarterSize)
- {
- width = (newActiveVideoRect.right - newActiveVideoRect.left) / 4;
- height = (newActiveVideoRect.bottom - newActiveVideoRect.top) / 4;
-
- gActiveVideoRect = newActiveVideoRect;
- SizeWindow (gMonitor, width, height, false);
- err = SGSetChannelBounds (gVideoChannel, &(gMonitor->portRect));
- }
- }
-
- // Has our crop changed?
- // This code shows how to be crop video panel friendly
- // Two important things -
- // 1) Be aware that you might have been cropped and adjust your
- // video window appropriately
- // 2) Be aware that you might have been adjusted and attempt to
- // account for this. Adjusting refers to using the digitizer
- // rect to "adjust" the active source rect within the maximum
- // source rect. This is useful if you're getting those nasty
- // black bands on the sides of your video display - you can use
- // the control-arrow key sequence to shift the active source
- // rect around when you're in the crop video panel
-
- adjustedActiveVideoRect = gActiveVideoRect;
- if (!MacEqualRect (&curVideoRect, &newVideoRect))
- {
- if ((newVideoRect.left < gActiveVideoRect.left) ||
- (newVideoRect.right > gActiveVideoRect.right) ||
- (newVideoRect.top < gActiveVideoRect.top) ||
- (newVideoRect.bottom > gActiveVideoRect.bottom))
- {
- if (newVideoRect.left < gActiveVideoRect.left)
- {
- adjustedActiveVideoRect.left = newVideoRect.left;
- adjustedActiveVideoRect.right -= (gActiveVideoRect.left - newVideoRect.left);
- }
- if (newVideoRect.right > gActiveVideoRect.right)
- {
- adjustedActiveVideoRect.right = newVideoRect.right;
- adjustedActiveVideoRect.left += (newVideoRect.right - gActiveVideoRect.right);
- }
- if (newVideoRect.top < gActiveVideoRect.top)
- {
- adjustedActiveVideoRect.top = newVideoRect.top;
- adjustedActiveVideoRect.bottom -= (gActiveVideoRect.top - newVideoRect.top);
- }
- if (newVideoRect.bottom > gActiveVideoRect.bottom)
- {
- adjustedActiveVideoRect.bottom = newVideoRect.bottom;
- adjustedActiveVideoRect.top += (newVideoRect.bottom - gActiveVideoRect.bottom);
- }
- newBounds = newVideoRect;
- MapRect (&newBounds, &adjustedActiveVideoRect, &(gMonitor->portRect));
- }
- else // Can't tell if we've been adjusted (digitizer rect is smaller on all sides
- // than the active source rect)
- {
- newBounds = newVideoRect;
- MapRect (&newBounds, &gActiveVideoRect, &(gMonitor->portRect));
- }
- width = newBounds.right - newBounds.left;
- height = newBounds.bottom - newBounds.top;
- err = SGSetChannelBounds (gVideoChannel, &newBounds);
- }
-
- // Clean out the part of the port that isn't being drawn in
- deadRgn = NewRgn();
- if (deadRgn != nil)
- {
- Rect boundsRect;
- err = SGGetChannelBounds (gVideoChannel, &boundsRect);
- err = XorRectToRgn (&boundsRect, &(gMonitor->portRect), &deadRgn);
- EraseRgn (deadRgn);
- DisposeRgn (deadRgn);
- }
-
- MacSetPort (savedPort);
-
- #if !TARGET_OS_MAC
- // This is necessary, for now, to get the grab to start again afer the
- // dialog goes away. For some reason the video destRect never gets reset to point
- // back to the monitor window.
- SGSetChannelBounds (gVideoChannel, &(gMonitor->portRect));
- #endif
-
- // The pause that refreshes
- err = SGPause (gSeqGrabber, false);
- }
-
- /* ---------------------------------------------------------------------- */
-
- void DoSoundSettings(void)
- {
- SGModalFilterUPP seqGragModalFilterUPP;
- ComponentResult err;
-
- seqGragModalFilterUPP = (SGModalFilterUPP)NewSGModalFilterProc(SeqGrabberModalFilterProc);
- err = SGSettingsDialog (gSeqGrabber, gSoundChannel, 0,
- nil, 0L, seqGragModalFilterUPP, (long) StripAddress ((Ptr) gMonitor));
- DisposeRoutineDescriptor(seqGragModalFilterUPP);
- }
-
- /* ---------------------------------------------------------------------- */
-
- void DoResize(short divisor)
- {
- short width, height;
- GrafPtr savedPort;
- Rect curBounds, maxBoundsRect;
- RgnHandle deadRgn;
- ComponentResult err;
-
- // New width and height
- width = (gActiveVideoRect.right - gActiveVideoRect.left) / divisor;
- height = (gActiveVideoRect.bottom - gActiveVideoRect.top) / divisor;
-
- gQuarterSize = (divisor == 4 ? true : false);
- gHalfSize = (divisor == 2 ? true : false);
- gFullSize = (divisor == 1 ? true : false);
-
- // Resize the monitor
- GetPort (&savedPort);
- MacSetPort (gMonitor);
- err = SGPause (gSeqGrabber, true);
- err = SGGetChannelBounds (gVideoChannel, &curBounds);
- maxBoundsRect = gMonitor->portRect;
- SizeWindow (gMonitor, width, height, false);
- MapRect (&curBounds, &maxBoundsRect, &(gMonitor->portRect));
- err = SGSetChannelBounds (gVideoChannel, &curBounds);
-
- // Clean out part of port we're not drawing in
- deadRgn = NewRgn();
- if (deadRgn != nil)
- {
- Rect boundsRect;
-
- err = SGGetChannelBounds (gVideoChannel, &boundsRect);
- err = XorRectToRgn (&boundsRect, &(gMonitor->portRect), &deadRgn);
- EraseRgn (deadRgn);
- DisposeRgn (deadRgn);
- }
-
- MacSetPort (savedPort);
- err = SGPause (gSeqGrabber, false);
- }
-
- /* ---------------------------------------------------------------------- */
-
- static OSErr XorRectToRgn (Rect *srcRectA, Rect *srcRectB, RgnHandle *destRgn)
- {
- RgnHandle srcRgnA = NewRgn();
- RgnHandle srcRgnB = NewRgn();
- OSErr result = noErr;
-
- if ((destRgn != nil) && (*destRgn != nil))
- {
- if ((srcRgnA != nil) &&
- (srcRgnB != nil))
- {
- RectRgn (srcRgnA, srcRectA);
- RectRgn (srcRgnB, srcRectB);
- MacXorRgn (srcRgnA, srcRgnB, *destRgn);
- DisposeRgn (srcRgnA);
- DisposeRgn (srcRgnB);
- }
- else
- {
- result = memFullErr;
- }
- }
- else
- {
- result = nilHandleErr;
- }
- return (result);
- }
-
- /* ---------------------------------------------------------------------- */
-